import requests, json
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from ui.config_ui import Ui_Dialog  # 导入配置页面的UI类 
from pathlib import Path

class RequestThread(QThread):
    response_received = Signal(str)
    error_occurred = Signal(str)
    progress_updated = Signal(int)  # 新增进度信号

    def __init__(self, url, method, headers=None, params=None):
        super().__init__()
        self.url = url
        self.method = method.upper()
        self.headers = headers or self.default_headers()
        self.params = params or {}

    def default_headers(self):
        return {
            'referer': self.url,
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0',
            'X-Requested-With': 'XMLHttpRequest',
            'Accept': '*/*',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        }

    def run(self):
        try:
            # 判断是否携带参数（无论GET/POST）
            has_params = bool(self.params)

            if self.method == "POST" or (self.method == "GET" and has_params):
                response = requests.request(
                    method=self.method,
                    url=self.url,
                    headers=self.headers,
                    data = self.params if has_params else None, # 动态处理参数
                    timeout=10,
                    stream=True  # 启用流式传输以获取进度
                )
            else:
                response = requests.get(
                    self.url,
                    params=self.params,
                    headers=self.default_headers(),
                    stream=True
                )
            response.raise_for_status()
            
            # 添加进度处理逻辑
            total_size = int(response.headers.get('content-length', 0))
            downloaded = 0
            self.progress_updated.emit(0)
            
            content = []  # 新增内容容器
            for chunk in response.iter_content(1024):
                downloaded += len(chunk)
                content.append(chunk)  # 累积数据块
                progress = int((downloaded / total_size) * 100) if total_size > 0 else 0
                self.progress_updated.emit(progress)
                
            # 合并数据并解码
            final_content = b''.join(content).decode('utf-8')
            self.response_received.emit(final_content)  # 发送完整内容
            
        except Exception as e:
            self.error_occurred.emit(str(e))

class BaseButtonManager:
    def __init__(self, ui_section, page_instance):
        self.ui = ui_section
        self.page = page_instance
        self.button = None
    
    def init_button(self):
        raise NotImplementedError
        
    def connect_signals(self):
        raise NotImplementedError

class RequestManager(BaseButtonManager):
    def init_button(self):
        self.button = self.ui.findChild(QPushButton, "pushButton_15")
        if not self.button:
            raise ValueError("请求按钮未找到")
        return self.button
    
    def connect_signals(self):
        self.button.clicked.connect(self._handle_request)
    
    def _handle_request(self):
        """处理带参数的HTTP请求"""
        url_edit = self.page.ui.findChild(QLineEdit, "lineEdit")
        method_combo = self.page.ui.findChild(QComboBox, "comboBox_4")
        
        url = url_edit.text().strip() if url_edit else ""
        method = method_combo.currentText().upper() if method_combo else "GET"
        
        if not url:
            self.page.update_response("错误:URL不能为空")
            return
            
        # 动态获取请求参数（GET/POST通用）
        request_params = self.page.current_config or {}
            
        self.page.prepare_ui_for_request()
        self.page._start_request_thread(url, method, request_params)  # 新增参数传递

class ClearManager(BaseButtonManager):
    def init_button(self):
        self.button = self.page.ui.findChild(QPushButton, "deletedata")
        if not self.button:
            raise ValueError("清除按钮未找到")
        return self.button
    
    def connect_signals(self):
        self.button.clicked.connect(self._clear_data)
    
    def _clear_data(self):
        """清除所有数据"""
        url_edit = self.page.ui.findChild(QLineEdit, "lineEdit")
        if url_edit:
            url_edit.clear()
            
        progress_bar = self.page.ui.findChild(QProgressBar, "progressBar")
        if progress_bar:
            progress_bar.setValue(0)
            
        self.page.update_response("")

class ConfigTableManager(BaseButtonManager):
    def init_button(self):
        self.button = self.page.ui.findChild(QPushButton, "pushButton_18")
        if not self.button:
            raise ValueError("配置表按钮未找到")
        return self.button
    
    def connect_signals(self):
        self.button.clicked.connect(self._open_config_table)

    def _open_config_table(self):
        """打开配置表"""
        try:
            dialog = QDialog()
            dialog.setWindowIcon(QIcon(":/icon/icons/cangku.png"))

            ui = Ui_Dialog()
            ui.setupUi(dialog)
            dialog.setWindowTitle("配置表")
            self.config_tab_ui = ui
            
            btn_handlers = {
                ui.pushButton_2: self._preview_config,
                ui.pushButton_3: self._delete_config,
                ui.pushButton_4: self._load_config
            }
            # 隐藏新建配置按钮
            ui.pushButton_5.setVisible(False)
            for btn, handler in btn_handlers.items():
                if btn == ui.pushButton_2:
                    btn.clicked.connect(handler)
                else:
                    btn.clicked.connect(lambda _, h=handler: (h(), dialog.accept())) 
            
            # 获取configs目录下的所有JSON文件
            config_files = list(self.page.config_dir.glob("*.json"))

            # 将配置文件添加到列表控件中
            list_widget = ui.listWidget  
            for file in config_files:
                item = QListWidgetItem(file.name)
                item.setSizeHint(QSize(100, 40))
                item.setIcon(QIcon('newProject\\icons\\file.png'))
                list_widget.addItem(item)

            dialog.exec()
        except Exception as e:
            self._show_error(f"打开配置表失败: {str(e)}")

    def _show_status(self, message):
        """显示状态消息(从ConfigTableManager移动至此)"""
        QMessageBox.information(
            self.ui,
            "操作成功",
            message,
            QMessageBox.StandardButton.Ok
        )
        
    def _show_error(self, message):
        """显示错误弹窗(从ConfigTableManager移动至此)"""
        QMessageBox.critical(
            self.ui,
            "操作失败",
            message,
            QMessageBox.StandardButton.Ok
        )

    def _preview_config(self):
        try:
            # 获取当前选中的配置文件
            selected_item = self.config_tab_ui.listWidget.currentItem()
            if not selected_item:
                QMessageBox.warning(None, "提示", "请先选择要预览的配置文件")
                return

            file_path = self.page.config_dir / selected_item.text()
            
            # 创建带格式的预览对话框
            preview_dialog = QDialog()
            preview_dialog.setWindowIcon(QIcon(":/icon/icons/preview.png"))
            preview_dialog.setWindowTitle(f"配置预览 - {file_path.name}")
            preview_dialog.resize(800, 600)
            
            # 创建带行号的文本编辑器
            text_edit = QPlainTextEdit()
            text_edit.setReadOnly(True)
            text_edit.setLineWrapMode(QPlainTextEdit.NoWrap)
            
            # 设置等宽字体
            font = QFont("Consolas", 10)
            text_edit.setFont(font)
            
            # 添加搜索框
            search_box = QLineEdit()
            search_box.setPlaceholderText("输入搜索内容...")
            
            # 布局设置
            layout = QVBoxLayout()
            layout.addWidget(search_box)
            layout.addWidget(text_edit)
            preview_dialog.setLayout(layout)
            
            # 加载并高亮JSON
            with open(file_path, 'r', encoding='utf-8') as f:
                raw_data = json.load(f)
                formatted_json = json.dumps(raw_data, indent=4, ensure_ascii=False)
                
                # 语法高亮
                highlighter = JSONHighlighter(text_edit.document())
                text_edit.setPlainText(formatted_json)
            
            # 实现搜索功能
            def search_text():
                cursor = text_edit.textCursor()
                cursor.beginEditBlock()  # 新增：开始编辑块
                cursor.movePosition(QTextCursor.Start)
                
                text_edit.extraSelections = []
                search_str = search_box.text().strip()
                
                if search_str:
                    format = QTextCharFormat()
                    format.setBackground(QColor(255, 255, 0, 100))  # 修改：添加透明度
                    format.setForeground(QColor(0, 0, 0))  # 新增：设置文字颜色
                    
                    # 修改：添加搜索选项（不区分大小写）
                    flags = QTextDocument.FindCaseSensitively | QTextDocument.FindWholeWords
                    while text_edit.find(search_str, flags):
                        selection = QTextEdit.ExtraSelection()
                        selection.format = format
                        selection.cursor = text_edit.textCursor()
                        text_edit.extraSelections.append(selection)
                cursor.endEditBlock()  # 新增：结束编辑块
                text_edit.setTextCursor(cursor)  # 新增：更新光标位置
            
            search_box.textChanged.connect(search_text)
            preview_dialog.exec_()

        except Exception as e:
            self._show_error(f"预览失败：{str(e)}")

    def _load_config(self):
        """加载配置到请求参数"""
        if selected := self.config_tab_ui.listWidget.currentItem():
            try:
                config_file = self.page.config_dir / selected.text()
                with open(config_file, 'r', encoding='utf-8') as f:
                    config_list = json.load(f)
                    # 新增格式转换：将列表转为字典
                    config_dict = {item["参数字段"]: item["参数值"] for item in config_list}
                    self.page.current_config = config_dict
                    self._show_status(f"已加载配置：{selected.text()}")
            except Exception as e:
                self._show_error(f"加载失败: {str(e)}")
        return None
    
    def _delete_config(self):
        """删除配置"""
        try:
            # 获取当前选中的配置项
            list_widget = self.config_storage_ui.listWidget
            if not list_widget.currentItem():
                self._show_error("请先选择要删除的配置")
                return
                
            # 获取文件路径
            selected_item = list_widget.currentItem()
            file_path = self.page.config_dir / selected_item.text()
            
            # 执行文件删除
            if file_path.exists():
                file_path.unlink()
            
            # 更新列表显示
            list_widget.takeItem(list_widget.row(selected_item))
            self._show_status(f"已删除配置：{file_path.name}")

        except Exception as e:
            self._show_error(f"删除失败：{str(e)}")

class DataManagerPage:
    def __init__(self, page_widget):
        self.ui = page_widget
        self.request_thread = None
        self._init_managers()
        self.config_dir = Path("configs")
        self.config_dir.mkdir(exist_ok=True)  # 确保配置目录存在
        self.current_config = {} # 初始化字典
        
    def _init_managers(self):
        """初始化按钮管理器"""
        self.managers = [
            RequestManager(self.ui, self),
            ClearManager(self.ui, self),
            ConfigTableManager(self.ui, self)  # 新增配置表管理器
        ]
        
        for manager in self.managers:
            try:
                manager.init_button()
                manager.connect_signals()
            except ValueError as e:
                print(f"按钮初始化错误: {str(e)}")

    def _start_request_thread(self, url, method, params):  # 添加params参数
        """启动请求线程（新增参数传递）"""
        self.request_thread = RequestThread(url, method, params)  # 传递params
        self.request_thread.response_received.connect(self.handle_success)
        self.request_thread.error_occurred.connect(self.handle_error)
        self.request_thread.progress_updated.connect(self.handle_progress)
        self.request_thread.start()

    def handle_progress(self, value):
        """新增进度处理方法"""
        progress_bar = self.ui.findChild(QProgressBar, "progressBar")  # 假设存在名为progressBar的控件
        if progress_bar:
            progress_bar.setValue(value)
            
    def prepare_ui_for_request(self):
        text_edit = self.ui.findChild(QPlainTextEdit, "plainTextEdit")
        btn = self.ui.findChild(QPushButton, "pushButton_15")
        progress_bar = self.ui.findChild(QProgressBar, "progressBar")  # 新增进度条初始化
        if text_edit and btn and progress_bar:
            text_edit.setPlainText("正在发送请求...")
            btn.setEnabled(False)
            progress_bar.setValue(0)  # 重置进度条
            
    def handle_success(self, data):
        text_edit = self.ui.findChild(QPlainTextEdit, "plainTextEdit")
        btn = self.ui.findChild(QPushButton, "pushButton_15")
        progress_bar = self.ui.findChild(QProgressBar, "progressBar")  # 新增进度条重置
        if text_edit and btn and progress_bar:
            text_edit.setPlainText(data)
            btn.setEnabled(True)
            progress_bar.setValue(100)  # 完成后设为100%
            
    def update_response(self, message):
        """统一更新响应信息"""
        text_edit = self.ui.findChild(QPlainTextEdit, "plainTextEdit")
        if text_edit:
            text_edit.setPlainText(message)

    def handle_error(self, error):
        self.update_response(f"请求失败：{error}")
        btn = self.ui.findChild(QPushButton, "pushButton_15")
        progress_bar = self.ui.findChild(QProgressBar, "progressBar")
        if btn and progress_bar:
            btn.setEnabled(True)
            progress_bar.setValue(0)

class JSONHighlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super().__init__(parent)
        
        self.key_format = QTextCharFormat()
        self.key_format.setForeground(QColor(200, 40, 150))
        
        self.value_format = QTextCharFormat()
        self.value_format.setForeground(QColor(30, 130, 210))
        
        self.string_format = QTextCharFormat()
        self.string_format.setForeground(QColor(30, 170, 40))

    def highlightBlock(self, text):
        # 匹配JSON键
        key_regex = QRegularExpression(r'\"(\w+)\"\s*:')
        match_iterator = key_regex.globalMatch(text)
        while match_iterator.hasNext():
            match = match_iterator.next()
            self.setFormat(match.capturedStart(), match.capturedLength(), self.key_format)
        
        # 匹配字符串值
        string_regex = QRegularExpression(r'\"[^"]*\"')
        match_iterator = string_regex.globalMatch(text)
        while match_iterator.hasNext():
            match = match_iterator.next()
            self.setFormat(match.capturedStart(), match.capturedLength(), self.string_format)
        
        # 匹配数值
        number_regex = QRegularExpression(r'\b\d+\b')
        match_iterator = number_regex.globalMatch(text)
        while match_iterator.hasNext():
            match = match_iterator.next()
            self.setFormat(match.capturedStart(), match.capturedLength(), self.value_format)